Skip to content

feat(telemetry-utils): deprecate LogLevel.default/error and tag unspecified events as essential#27207

Open
MarioJGMsoft wants to merge 29 commits intomicrosoft:mainfrom
MarioJGMsoft:marioja/deprecateLogLevel
Open

feat(telemetry-utils): deprecate LogLevel.default/error and tag unspecified events as essential#27207
MarioJGMsoft wants to merge 29 commits intomicrosoft:mainfrom
MarioJGMsoft:marioja/deprecateLogLevel

Conversation

@MarioJGMsoft
Copy link
Copy Markdown
Contributor

@MarioJGMsoft MarioJGMsoft commented Apr 29, 2026

Description

Tracks issue #26969 (planned removal in v3.0).

This PR has two parts:

1. Deprecate LogLevel.default and LogLevel.error

Adds @deprecated tags on LogLevel.default and LogLevel.error and migrates
all in-repo callsites:

Adds @deprecated tags on LogLevel.default and LogLevel.error in @fluidframework/core-interfaces and migrates all in-repo callsites:

Affected files include telemetry-utils (logger.ts, mockLogger.ts, telemetryTypes.ts, and the related tests) and the corresponding API reports.

2. Treat events with no explicit logLevel as essential in TelemetryLogger

Two related changes in packages/utils/telemetry-utils/src/logger.ts:

  • ChildLogger.shouldFilterOutEvent now falls back to LogLevel.essential (30) when an event arrives without a logLevel (previously LogLevel.default = 20).
  • ChildLogger.send now forwards LogLevel.essential to the base logger when no logLevel was supplied, instead of forwarding undefined.

Additionally, the parameter defaults on TelemetryLogger.sendTelemetryEvent and sendPerformanceEvent were dropped (they were = LogLevel.default). Callers that don't pass a logLevel now propagate undefined through the chain, where ChildLogger applies the new essential fallback above.

3. createSampledLogger and MultiSinkLogger.send now forward error and logLevel

Two pre-existing bugs surfaced while wiring up the essential fallback above:

  • createSampledLogger (packages/utils/telemetry-utils/src/utils.ts) silently dropped error and logLevel arguments before delegating to the wrapped logger — the wrapper's method signatures didn't even accept those arguments. The wrapper now accepts and forwards them:

    • send accepts logLevel?
    • sendTelemetryEvent accepts error? and logLevel? (verbose | info)
    • sendErrorEvent accepts error?
    • sendPerformanceEvent accepts error? and logLevel? (verbose | info)
  • MultiSinkLogger.send (packages/utils/telemetry-utils/src/logger.ts) had the same bug — logLevel was dropped before fanning out to sinks. It now accepts logLevel? and forwards it to every registered sink (defaulting to LogLevel.essential when omitted, consistent with the part 2 behavior).

New test coverage:

  • telemetryLogger.spec.ts — new describe("logLevel forwarding") covering sendTelemetryEvent, sendPerformanceEvent, and sendErrorEvent: default fallback to essential, explicit info forwarding, and category: "error" upgrading to essential even when info was requested. (These tests live on the parent class because sendTelemetryEvent / sendPerformanceEvent are implemented there, not on ChildLogger.)
  • childLogger.spec.tsdescribe("logLevel forwarding") verifies ChildLogger.send propagates the level through to the underlying sink (essential default, explicit info, and verbose once the sink opts in via minLogLevel).
  • multiSinkLogger.spec.tsdescribe("logLevel propagation") verifies the essential fallback, explicit-level forwarding for both sendTelemetryEvent and sendPerformanceEvent, and includes a regression test for the MultiSinkLogger.send drop bug.
  • utils.spec.tsdescribe("logLevel forwarding") verifies the sampled logger forwards logLevel through send, sendTelemetryEvent, and sendPerformanceEvent, and propagates undefined when the caller omits it.

Misc

  • Fixed an incorrect type import ordering in container.spec.ts.

Behavior change for downstream consumers

Although no public API is removed in this PR, downstream consumers that filter telemetry by numeric level should be aware:

Internal Fluid events that were previously emitted to the base logger with
logLevel = undefined (effectively treated as 20) will now arrive tagged as
30 (essential). If a host application starts dropping logLevel = 20 events
as "non-essential", it must ensure all running Fluid versions include this
change — older Fluid versions still send those same critical events at level
20, and dropping them would lose telemetry.

Breaking Changes

No public API surface is removed. See #26969 for the planned v3.0 removal of LogLevel.default and LogLevel.error. See the "Behavior change for downstream consumers" section above for a runtime behavior note.

Reviewer Guidance

The review process is outlined on this wiki page.

Specific asks:

  • Confirm the LogLevel.essential fallback in ChildLogger.shouldFilterOutEvent and ChildLogger.send is the intended semantic (vs. leaving undefined to flow to the base logger).
  • Confirm dropping the = LogLevel.default parameter defaults on sendTelemetryEvent / sendPerformanceEvent is acceptable for consumers who may have relied on the implicit default.
  • Confirm the createSampledLogger and MultiSinkLogger.send argument forwarding fix is acceptable as part of this PR (it changes observable behavior for hosts wrapping with these helpers).

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 29, 2026

Hi! Thank you for opening this PR. Want me to review it?

Based on the diff (102 lines, 13 files), I've queued these reviewers:

  • Correctness — logic errors, race conditions, lifecycle issues
  • Security — vulnerabilities, secret exposure, injection
  • API Compatibility — breaking changes, release tags, type design
  • Performance — algorithmic regressions, memory leaks
  • Testing — coverage gaps, hollow tests

Toggle the reviewer checkboxes above to adjust, then tick the box below to start:

  • Start review

@MarioJGMsoft MarioJGMsoft changed the title feat: deprecate LogLevel.default and LogLevel.error feat(telemetry-utils): deprecate LogLevel.default/error and tag unspecified events as essential Apr 29, 2026
@MarioJGMsoft MarioJGMsoft marked this pull request as ready for review April 30, 2026 16:22
@MarioJGMsoft MarioJGMsoft requested a review from a team as a code owner April 30, 2026 16:22
Copilot AI review requested due to automatic review settings April 30, 2026 16:22
@MarioJGMsoft MarioJGMsoft requested a review from a team as a code owner April 30, 2026 16:22
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates Fluid’s telemetry log-level semantics by deprecating legacy LogLevel members and changing how ChildLogger treats events with no explicit logLevel, to better distinguish “essential” telemetry.

Changes:

  • Deprecates LogLevel.default and LogLevel.error, and migrates in-repo usages to LogLevel.info / LogLevel.essential.
  • Changes ChildLogger to treat events with no explicit logLevel as essential, including forwarding essential to the base logger.
  • Updates related types/docs, tests, API reports, and adds changesets documenting the behavior change.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
packages/utils/telemetry-utils/src/test/multiSinkLogger.spec.ts Updates tests to use info/essential instead of deprecated default/error.
packages/utils/telemetry-utils/src/test/childLogger.spec.ts Updates log-level constants in tests; should be extended to cover the new “unspecified logLevel ⇒ essential” behavior.
packages/utils/telemetry-utils/src/telemetryTypes.ts Updates logLevel unions to use info; updates TSDoc (currently inconsistent with new runtime defaults).
packages/utils/telemetry-utils/src/mockLogger.ts Updates MockLogger default min level / filtering fallback from default to info.
packages/utils/telemetry-utils/src/logger.ts Removes parameter defaults, changes ChildLogger fallback/forwarding to essential, updates MultiSink defaults, and adds PerformanceEvent docs (currently inaccurate).
packages/utils/telemetry-utils/api-report/telemetry-utils.legacy.beta.api.md API report update reflecting new logLevel unions.
packages/loader/container-loader/src/test/container.spec.ts Import ordering/type-only import adjustment.
packages/common/core-interfaces/src/logger.ts Adds @deprecated tags for LogLevelConst.default/error and updates base logger docs to default to info.
packages/common/core-interfaces/api-report/core-interfaces.public.api.md API report reflects deprecated members.
packages/common/core-interfaces/api-report/core-interfaces.legacy.public.api.md API report reflects deprecated members.
packages/common/core-interfaces/api-report/core-interfaces.legacy.beta.api.md API report reflects deprecated members.
packages/common/core-interfaces/api-report/core-interfaces.legacy.alpha.api.md API report reflects deprecated members.
packages/common/core-interfaces/api-report/core-interfaces.beta.api.md API report reflects deprecated members.
.changeset/soft-doors-trade.md Changeset documenting the ChildLogger unspecified-logLevel behavior change and downstream impact.
.changeset/salty-colts-appear.md Changeset documenting the LogLevel.default/error deprecations and migration guidance.

Comment thread packages/utils/telemetry-utils/src/logger.ts
Comment thread packages/utils/telemetry-utils/src/logger.ts Outdated
Comment thread packages/utils/telemetry-utils/src/telemetryTypes.ts
Comment thread packages/utils/telemetry-utils/src/telemetryTypes.ts
Comment thread packages/utils/telemetry-utils/src/test/childLogger.spec.ts Outdated
Comment thread packages/utils/telemetry-utils/src/logger.ts
Comment thread packages/utils/telemetry-utils/src/logger.ts
Comment thread packages/loader/container-loader/src/test/container.spec.ts
* Log a telemetry event, if it meets the appropriate log-level threshold (see {@link ITelemetryBaseLogger.minLogLevel}).
* @param event - The event to log.
* @param logLevel - The log level of the event. Default: {@link LogLevelConst.default | LogLevel.default}.
* @param logLevel - The log level of the event. Default: {@link LogLevelConst.info | LogLevel.info}.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the default supposed to be essential? Maybe it's clearer if we say it like "suggested interpretation of undefined: LogLevel.essential"? Since this is an interface so claiming a "default value" is kind of in vain, it could be implemented any way.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied change

@MarioJGMsoft MarioJGMsoft linked an issue May 4, 2026 that may be closed by this pull request
Comment thread packages/utils/telemetry-utils/src/logger.ts Outdated
Removes 11 zero-byte files added by mistake in 2c13181. These are
bind-mounted from the dev container host (shell rc files, IDE config,
MCP config) and don't belong in the repo.
Copy link
Copy Markdown
Contributor

@jason-ha jason-ha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few docs and test suggestions. Thanks!

Comment thread packages/utils/telemetry-utils/src/logger.ts Outdated
Comment thread packages/utils/telemetry-utils/src/logger.ts Outdated
Comment thread packages/utils/telemetry-utils/src/telemetryTypes.ts Outdated
Comment thread packages/utils/telemetry-utils/src/test/childLogger.spec.ts
Comment thread packages/utils/telemetry-utils/src/test/childLogger.spec.ts Outdated
Comment thread .changeset/salty-colts-appear.md Outdated
Comment thread .changeset/salty-colts-appear.md Outdated
Comment thread packages/utils/telemetry-utils/src/test/childLogger.spec.ts Outdated
@jason-ha
Copy link
Copy Markdown
Contributor

jason-ha commented May 7, 2026

Please also remember to update your PR description

Copy link
Copy Markdown
Contributor

@jason-ha jason-ha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to approve - you'll need docs sign-off anyway

Comment thread .changeset/salty-colts-appear.md Outdated

- For an **event's `logLevel`** (e.g. the `logLevel` argument to `sendTelemetryEvent` / `sendPerformanceEvent` / `ITelemetryBaseLogger.send`), the recommendation is `LogLevel.essential`.
- For a logger's **`minLogLevel`** (the threshold that filters events), `LogLevel.info` is the recommendation.
- For an **event's default `logLevel`** (e.g. the `logLevel` argument to `sendTelemetryEvent` / `sendPerformanceEvent` / `ITelemetryBaseLogger.send`), the recommendation is `LogLevel.essential`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a little funny because we don't want anyone implementing sendTelemetryEvent / sendPerformanceEvent. Just ITelemetryBaseLogger.send will do.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied change

Comment thread .changeset/salty-colts-appear.md Outdated
- For an **event's default `logLevel`** (e.g. the `logLevel` argument to `sendTelemetryEvent` / `sendPerformanceEvent` / `ITelemetryBaseLogger.send`), the recommendation is `LogLevel.essential`.
- For a logger's **default `minLogLevel`** (the threshold that filters events), `LogLevel.info` is the recommendation.

The replacement for `LogLevel.error` should always be essential.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"essential" -> "LogLevel.essential" so the replacement is symmetric with the source.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied change

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 8, 2026

🔗 No broken links found! ✅

Your attention to detail is admirable.

linkcheck output


> fluid-framework-docs-site@0.0.0 ci:check-links /home/runner/work/FluidFramework/FluidFramework/docs
> start-server-and-test "npm run serve -- --no-open" 3000 check-links

1: starting server using command "npm run serve -- --no-open"
and when url "[ 'http://127.0.0.1:3000' ]" is responding with HTTP status code 200
running tests using command "npm run check-links"


> fluid-framework-docs-site@0.0.0 serve
> docusaurus serve --no-open

[SUCCESS] Serving "build" directory at: http://localhost:3000/

> fluid-framework-docs-site@0.0.0 check-links
> linkcheck http://localhost:3000 --skip-file skipped-urls.txt

Crawling...

Stats:
  288641 links
    1922 destination URLs
    2172 URLs ignored
       0 warnings
       0 errors


@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 8, 2026

🔗 No broken links found! ✅

Your attention to detail is admirable.

linkcheck output


> fluid-framework-docs-site@0.0.0 ci:check-links /home/runner/work/FluidFramework/FluidFramework/docs
> start-server-and-test "npm run serve -- --no-open" 3000 check-links

1: starting server using command "npm run serve -- --no-open"
and when url "[ 'http://127.0.0.1:3000' ]" is responding with HTTP status code 200
running tests using command "npm run check-links"


> fluid-framework-docs-site@0.0.0 serve
> docusaurus serve --no-open

[SUCCESS] Serving "build" directory at: http://localhost:3000/

> fluid-framework-docs-site@0.0.0 check-links
> linkcheck http://localhost:3000 --skip-file skipped-urls.txt

Crawling...

Stats:
  288641 links
    1922 destination URLs
    2172 URLs ignored
       0 warnings
       0 errors


Copy link
Copy Markdown
Contributor

@jzaffiro jzaffiro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nit, but approved for docs!

Comment thread .changeset/salty-colts-appear.md Outdated
"__section": deprecation
---

Deprecated LogLevel.default and LogLevel.error
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Deprecated LogLevel.default and LogLevel.error
Deprecate LogLevel.default and LogLevel.error

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied change

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 8, 2026

🔗 No broken links found! ✅

Your attention to detail is admirable.

linkcheck output


> fluid-framework-docs-site@0.0.0 ci:check-links /home/runner/work/FluidFramework/FluidFramework/docs
> start-server-and-test "npm run serve -- --no-open" 3000 check-links

1: starting server using command "npm run serve -- --no-open"
and when url "[ 'http://127.0.0.1:3000' ]" is responding with HTTP status code 200
running tests using command "npm run check-links"


> fluid-framework-docs-site@0.0.0 serve
> docusaurus serve --no-open

[SUCCESS] Serving "build" directory at: http://localhost:3000/

> fluid-framework-docs-site@0.0.0 check-links
> linkcheck http://localhost:3000 --skip-file skipped-urls.txt

Crawling...

Stats:
  288641 links
    1922 destination URLs
    2172 URLs ignored
       0 warnings
       0 errors


return;
}
this.baseLogger.send(this.prepareEvent(event), logLevel);
this.baseLogger.send(this.prepareEvent(event), logLevel ?? LogLevel.essential);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened to making logLevel required on send for the sub-classes? Now we have two places in the same flow filling in defaults

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It couldn't be made there might still be chances that ChildLogger and Multisink receive undefined from old containerRuntime (At least that's what I understood). @jason-ha to confirm

* @param error - Optional error object to log.
* @param logLevel - Optional level of the log. Default: {@link @fluidframework/core-interfaces#LogLevel.essential}.
* @param logLevel - Optional level of the log. If undefined, the logLevel should be treated as {@link @fluidframework/core-interfaces#LogLevel.essential}.
* If the event's category is `error`, the logLevel will be upgraded to {@link @fluidframework/core-interfaces#LogLevel.essential}.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super nit:

Suggested change
* If the event's category is `error`, the logLevel will be upgraded to {@link @fluidframework/core-interfaces#LogLevel.essential}.
* If the event's category is `error`, the logLevel should be upgraded to {@link @fluidframework/core-interfaces#LogLevel.essential}.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is referring to the flow in sendTelemetryEvent and sendPerformanceEvent , where they do this: event.category === "error" ? LogLevel.essential : (logLevel ?? LogLevel.essential), so if it's an error, we will upgrade it to essential no matter what.

logLevel?: typeof LogLevel.verbose | typeof LogLevel.info,
): void;

/**
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a note here that it's going to use logLevel essential?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're referring to sendTelemetryEvent, that note already exists on line 188. If you're referring to sendErrorEvent, since the change itself doesn't affect the interface, I don't think it's necessary to comment that there.

Copy link
Copy Markdown
Member

@markfields markfields left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM overall

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove deprecated LogLevel.default and LogLevel.error

5 participants